package physicalObjects;
import simulation.Simulation;
import forces.Force;

/**
 * @author Qiang Fu
 */
public class Bar extends Spring {
    /**
     * A large k constant to make the spring hard to expand or shrink
     * to behave like a bar.
     */
    private static final double KCONST = 2.5;
    /**
     * A damping force is applied to masses to stop oscillation, whose
     * amplitude is proportional to the mass velocity but with opposite
     * direction.
     */
    private static final double DAMPCONST = 0.5;
    /**
     * The oscillation is detected once the change in bar length is
     * greater than this value.
     */
    private static final double THRESHOLD = 1;

    /**
     * Constructor for this class.
     * @param start Mass on start end of the muscle
     * @param end Mass on end of muscle
     * @param length Rest length of the bar
     * @param kVal k value associated with the spring/bar
     */
    public Bar(Mass start, Mass end, double length, double kVal) {
        super(start, end, length, KCONST);
        // TODO Auto-generated constructor stub
    }

    /**
     * @param canvas The simulation where this is running
     * @param dt Time changes
     */
    public void update(Simulation canvas, double dt) {
        super.update(canvas, dt);

        /**
         * Get the velocity of each mass
         */
        Force startMassVelocity = getMyStart().getVelocity();
        Force endMassVelocity = getMyEnd().getVelocity();
        /**
         * The distances on x and y axises
         */
        double dx = getMyStart().getCenter().getX()
                - getMyEnd().getCenter().getX();
        double dy = getMyStart().getCenter().getY()
                - getMyEnd().getCenter().getY();

        /**
         * Detect the oscillation and apply the damping force
         */
        if (Force.distanceBetween(dx, dy) < getMyLength() - THRESHOLD
                || Force.distanceBetween(dx, dy) > getMyLength() + THRESHOLD) {
            /**
             * The damping force to be applied to the masses. Define the
             * direction towards the center of the bar as the direction of the
             * force.
             */
            Force dampStart = new Force(Force.angleBetween(-dx, -dy), 0);
            Force dampEnd = new Force(Force.angleBetween(dx, dy), 0);
            /**
             * Get the oscillation velocity by projecting the mass velocity
             * along the direction of the bar.
             */
            double velocityStartmassBar =
                    -startMassVelocity.getRelativeMagnitude(dampStart);
            double velocityEndmassBar =
                    -endMassVelocity.getRelativeMagnitude(dampEnd);
            /**
             * The magnitude of the damping force is proportional to the
             * oscillation velocity.
             */
            dampStart.setMagnitude(-velocityStartmassBar * DAMPCONST);
            dampEnd.setMagnitude(-velocityEndmassBar * DAMPCONST);

            getMyStart().applyForce(dampStart);
            getMyEnd().applyForce(dampEnd);
        }
    }
}
